use crate::component::request::{Method, Request, RequestBody};
use crate::component::response::Response;
use reqwest::header::HeaderMap;
use reqwest::header::HeaderValue;
use reqwest::Client;
use std::collections::HashMap;

#[derive(Clone)]
pub struct Downloader {
    client: Client,
}

impl Downloader {
    /// 可以设置公共请求头
    pub fn new(headers: Option<HashMap<&'static str, String>>) -> Self {
        let mut hm = HeaderMap::new();
        match headers {
            Some(header_map) => {
                for (k, v) in header_map {
                    hm.append(k, HeaderValue::from_str(&v).unwrap());
                }
            }
            None => {}
        }
        Self {
            client: Client::builder()
                .user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:86.0) Gecko/20100101 Firefox/86.0")
                .cookie_store(true)
                .default_headers(hm)
                .build()
                .unwrap(),
        }
    }

    /// TODO: send json
    pub async fn download(&self, req: Request) -> Result<Response, reqwest::Error> {
        let Request {
            url,
            method,
            headers,
            query,
            body,
        } = req.clone();

        // method
        let mut rb = match method {
            Method::GET => self.client.get(url),
            Method::POST => self.client.post(url),
        };

        // 设置本次请求头
        if let Some(headers) = headers {
            let mut hm = HeaderMap::new();
            for (k, v) in headers {
                hm.append(k, HeaderValue::from_str(&v).unwrap());
            }
            rb = rb.headers(hm);
        }

        // 构建 query
        if let Some(query) = query {
            rb = rb.query(&query);
        }

        match body {
            RequestBody::Form(data) => {
                rb = rb.form(&data);
            }
            RequestBody::Empty => {}
        }

        match rb.send().await {
            Ok(resp) => Ok(Response::new(req.url, resp)),
            Err(e) => Err(e),
        }
    }
}
